package com.hackordie.controllers;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.hackordie.bindables.BindableComponent;
import com.hackordie.bindables.BindableComputerType;
import com.hackordie.bindables.BindableRole;
import com.hackordie.commons.authorities.Role;
import com.hackordie.commons.authorities.User;
import com.hackordie.commons.hardware.components.AComponent;
import com.hackordie.commons.hardware.components.Firewall;
import com.hackordie.commons.hardware.components.HardDisk;
import com.hackordie.commons.hardware.components.NetworkCard;
import com.hackordie.commons.hardware.components.PowerSupply;
import com.hackordie.commons.hardware.components.Processor;
import com.hackordie.commons.hardware.components.RamMemory;
import com.hackordie.commons.hardware.computer.ComputerType;

@Controller
@RequestMapping(value = "/admin")
public class AdminController extends AMainController {

    //pagina inicial admin
	@RequestMapping(value = "/dashboard", method = RequestMethod.GET)
	public String login(ModelMap model, HttpServletRequest request) throws Exception {
		breadCrumbService.addNode("Admin", 0, request);
		return "admin/dashboard";
	}

	//*******************************************************************************//
	//************************ administracion de usuarios ***************************//	
	//*******************************************************************************//
	
	@RequestMapping(value = "/users", method = RequestMethod.GET)
	public String users(ModelMap model, HttpServletRequest request) throws Exception {
		breadCrumbService.addNode("User Management", 1, request);
		return "redirect:/admin/users/pages/1";
	}

	@RequestMapping(value = "/users/pages/{page}", method = RequestMethod.GET)
	public String page(@PathVariable("page") int page, ModelMap model, HttpServletRequest request) throws Exception {
		breadCrumbService.addNode("Page " + page, 2, request);

		int PAGE_FIELDS = 10;
		int pages = (int) Math.ceil((double) hodManager.countAllUsers() / (double) PAGE_FIELDS);
		int begin = Math.max(1, page - 5);
		int end = Math.min(begin + 10, pages);

		model.addAttribute("totalPages", pages);
		model.addAttribute("beginIndex", begin);
		model.addAttribute("endIndex", end);
		model.addAttribute("currentIndex", page);

		int first = (page - 1) * PAGE_FIELDS;

		model.addAttribute("users", hodManager.getAllUsersByRange(first, PAGE_FIELDS));
		model.addAttribute("active_users", "active");
		return "admin/users";
	}

	@RequestMapping(value = "/users/delete/{idUser}", method = RequestMethod.GET)
	public String usersdelete(@PathVariable("idUser") int idUser, ModelMap model) throws Exception {
		hodManager.deleteUser(idUser);
		return "redirect:/admin/users/pages/1";
	}

	@RequestMapping(value = "/users/block/{idUser}", method = RequestMethod.GET)
	public String usersblock(@PathVariable("idUser") int idUser, ModelMap model) throws Exception {
		hodManager.disableUser(idUser);
		return "redirect:/admin/users/pages/1";
	}
	
	@RequestMapping(value = "/users/unblock/{idUser}", method = RequestMethod.GET)
    public String usersunblock(@PathVariable("idUser") int idUser, ModelMap model) throws Exception {
        hodManager.enableUser(idUser);
        return "redirect:/admin/users/pages/1";
    }
	
	 @RequestMapping(value = "/changeRole/{idUser}", method = RequestMethod.POST)
	    public String changeUserRole(@PathVariable("idUser") int idUser, ModelMap model, @Valid @ModelAttribute("bindableRole") Role role, BindingResult result)
	            throws Exception {    
	        
	        User user = hodManager.getUser(idUser);        
	        user.setRole(Integer.parseInt(role.getName()));        
	        hodManager.updateUser(user);
	        
	        return "redirect:/user/profile/" + idUser;  //TODO ir a la pagina adecuada
	    }
	
	//*******************************************************************************//
	//*******************************************************************************//
	//*******************************************************************************//
	
	//*******************************************************************************//
	//************************* administracion de roles *****************************//
	//*******************************************************************************//

	@RequestMapping(value = "/roles", method = RequestMethod.GET)
	public String roles(ModelMap model, HttpServletRequest request) throws Exception {
		breadCrumbService.addNode("Roles Management", 1, request);
		model.addAttribute("active_roles", "active");
		return "redirect:/admin/roles/pages/1";
	}
	
	@RequestMapping(value = "/roles/pages/{page}", method = RequestMethod.GET)
    public String rolesPage(@PathVariable("page") int page, ModelMap model, HttpServletRequest request) throws Exception {
        breadCrumbService.addNode("Page " + page, 2, request);

        int PAGE_FIELDS = 10;
        int pages = (int) Math.ceil((double) hodManager.countAllRoles() / (double) PAGE_FIELDS);
        int begin = Math.max(1, page - 5);
        int end = Math.min(begin + 10, pages);

        model.addAttribute("totalPages", pages);
        model.addAttribute("beginIndex", begin);
        model.addAttribute("endIndex", end);
        model.addAttribute("currentIndex", page);

        int first = (page - 1) * PAGE_FIELDS;

        Role[] roles =  hodManager.getRoleByRange(first, PAGE_FIELDS);
        
        model.addAttribute("roles", roles);
        model.addAttribute("active_roles", "active");
        return "admin/roles";
    }
    
    @RequestMapping(value = "/roles/delete/{idRole}", method = RequestMethod.GET)
    public String rolesDelete(@PathVariable("idRole") int idRole, ModelMap model) throws Exception {
        hodManager.deleteRole(idRole);
        return "redirect:/admin/roles/pages/1";
    }
    
    @RequestMapping(value = "/roles/block/{idRole}", method = RequestMethod.GET)
    public String rolesBlock(@PathVariable("idRole") int idRole, ModelMap model) throws Exception {
        hodManager.disableRole(idRole);
        return "redirect:/admin/roles/pages/1";
    }
    
    @RequestMapping(value = "/roles/unblock/{idRole}", method = RequestMethod.GET)
    public String rolesUnBlock(@PathVariable("idRole") int idRole, ModelMap model) throws Exception {
        hodManager.enableRole(idRole);
        return "redirect:/admin/roles/pages/1";
    }
    
    @RequestMapping(value = "/role/formAdd", method = RequestMethod.GET)
    public String formAddRole(ModelMap model, HttpServletRequest request) throws Exception {
        breadCrumbService.addNode("New role", 2, request);
        model.addAttribute(new BindableRole());
        return "admin/formAddRole";
    }
    
    @RequestMapping(value = "/addRole", method = RequestMethod.POST)
    public String addRole(ModelMap model, @Valid @ModelAttribute("bindableRole") Role role, BindingResult result)
            throws Exception {        
        model.addAttribute("sucess", hodManager.createRole(role));
        return "admin/formAddRole";
    }
       
	
	//*******************************************************************************//
    //*******************************************************************************//
    //*******************************************************************************//
    
    //*******************************************************************************//
    //********************** administracion de computer type ************************//
    //*******************************************************************************//
	
	@RequestMapping(value = "/computerType", method = RequestMethod.GET)
    public String computerType(ModelMap model, HttpServletRequest request) throws Exception {
	    breadCrumbService.addNode("Computer type Management", 1, request);
        return "redirect:/admin/computerType/pages/1";
    }
	
	@RequestMapping(value = "/computerType/pages/{page}", method = RequestMethod.GET)
    public String computerTypePage(@PathVariable("page") int page, ModelMap model, HttpServletRequest request) throws Exception {
        breadCrumbService.addNode("Page " + page, 2, request);

        int PAGE_FIELDS = 10;
        int pages = (int) Math.ceil((double) hodManager.countAllComputerType() / (double) PAGE_FIELDS);
        int begin = Math.max(1, page - 5);
        int end = Math.min(begin + 10, pages);

        model.addAttribute("totalPages", pages);
        model.addAttribute("beginIndex", begin);
        model.addAttribute("endIndex", end);
        model.addAttribute("currentIndex", page);

        int first = (page - 1) * PAGE_FIELDS;

        ComputerType[] cp =  hodManager.getAllComputerTypeByRange(first, PAGE_FIELDS);
        
        model.addAttribute("computersType", cp);
        model.addAttribute("active_computer_type", "active");
        return "admin/computerType";
    }
	
	@RequestMapping(value = "/computerType/delete/{idComputerType}", method = RequestMethod.GET)
    public String computerTypedelete(@PathVariable("idComputerType") int idComputerType, ModelMap model) throws Exception {
        hodManager.deleteComputerType(idComputerType);
        return "redirect:/admin/computerType/pages/1";
    }
	
	@RequestMapping(value = "/computerType/formAdd", method = RequestMethod.GET)
    public String formAddcomputerType(ModelMap model, HttpServletRequest request) throws Exception {
        breadCrumbService.addNode("New computer type", 2, request);
        model.addAttribute(new BindableComputerType());
        return "admin/formAddComputerType";
    }

	@RequestMapping(value = "/addComputerType", method = RequestMethod.POST)
    public String addComputerType(ModelMap model, @Valid @ModelAttribute("bindableComputerType") ComputerType ComputerType, BindingResult result)
            throws Exception {	 
	    
        model.addAttribute("sucess", hodManager.addComputerType(ComputerType));
        return "admin/formAddComputerType";
    }
	
	
	//*******************************************************************************//
    //*******************************************************************************//
    //*******************************************************************************//
    
    //*******************************************************************************//
    //*********************** administracion de components **************************//
    //*******************************************************************************//
	
	@RequestMapping(value = "/components", method = RequestMethod.GET)
    public String comonents(ModelMap model, HttpServletRequest request) throws Exception {
        breadCrumbService.addNode("Components Management", 1, request);
        return "redirect:/admin/components/pages/1";
    }
    
    @RequestMapping(value = "/components/pages/{page}", method = RequestMethod.GET)
    public String componentsPage(@PathVariable("page") int page, ModelMap model, HttpServletRequest request) throws Exception {
        breadCrumbService.addNode("Page " + page, 2, request);

        int PAGE_FIELDS = 10;
        int pages = (int) Math.ceil((double) hodManager.countAllComponents() / (double) PAGE_FIELDS);
        int begin = Math.max(1, page - 5);
        int end = Math.min(begin + 10, pages);

        model.addAttribute("totalPages", pages);
        model.addAttribute("beginIndex", begin);
        model.addAttribute("endIndex", end);
        model.addAttribute("currentIndex", page);

        int first = (page - 1) * PAGE_FIELDS;
        int last = first + (PAGE_FIELDS);

        AComponent[] components =  hodManager.getAllComponentsByRange(first, last);
        
        model.addAttribute("components", components);
        model.addAttribute("active_components", "active");
        return "admin/components";
    }
    
    @RequestMapping(value = "/components/delete/{idComponent}", method = RequestMethod.GET)
    public String componentdelete(@PathVariable("idComponent") int idComponent, ModelMap model) throws Exception {
        hodManager.deleteComponents(idComponent);
        return "redirect:/admin/components/pages/1";  //TODO volver a la pagina actual, no a la primera
    }
    
    @RequestMapping(value = "/components/formAdd", method = RequestMethod.GET)
    public String formAddcomponents(ModelMap model, HttpServletRequest request) throws Exception {
        breadCrumbService.addNode("New component", 2, request);
        model.addAttribute(new BindableComponent());
        return "admin/formAddComponent";
    }

    @RequestMapping(value = "/addComponent", method = RequestMethod.POST)
    public String addComponents(ModelMap model, @Valid @ModelAttribute("bindableComponent") BindableComponent component, BindingResult result)
            throws Exception {   
        
        switch(component.getComponentType()) {
        case Firewall:
            model.addAttribute("sucess", hodManager.addComponents(new Firewall(component.getComponentName(),
                                                                               component.getEnergyToTurnOn(),
                                                                               component.getDificultAccess(),
                                                                               component.getPrize())));    
            break;            
        case HardDisk:
            model.addAttribute("sucess", hodManager.addComponents(new HardDisk(component.getComponentName(),
                                                                               component.getEnergyToTurnOn(),
                                                                               component.getTotalCapacity(),
                                                                               component.getPrize())));  
             break;
                    
        case NetworkCard:
            model.addAttribute("sucess", hodManager.addComponents(new NetworkCard(component.getComponentName(),
                                                                                  component.getEnergyToTurnOn(),
                                                                                  "",       //la ipDirection no se almacena
                                                                                  component.getSpeedConection(),
                                                                                  component.getPrize())));
            break;
            
        case PowerSupply:
            model.addAttribute("sucess", hodManager.addComponents(new PowerSupply(component.getComponentName(),
                                                                                  component.getGeneratedEnergy(),
                                                                                  component.getPrize())));
            break;
            
        case RamMemory:
            model.addAttribute("sucess", hodManager.addComponents(new RamMemory(component.getComponentName(),
                                                                                component.getEnergyToTurnOn(),
                                                                                component.getTotalCapacity(),
                                                                                component.getPrize())));
            break;
            
        case Processor:
            model.addAttribute("sucess", hodManager.addComponents(new Processor(component.getComponentName(),
                                                                                component.getEnergyToTurnOn(),
                                                                                component.getSpeedForCore(),
                                                                                component.getCores(),
                                                                                0,          //levelSkill no se almacena
                                                                                component.getPrize())));
            break;           
        }      
        return "admin/formAddComponent";
    }
    
    //*******************************************************************************//
    //*******************************************************************************//
    //*******************************************************************************//
}
